/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.cachecontrol.cacheFactories;

import com.softwarecraftsmen.cachecontrol.ComptrolledCache;
import com.softwarecraftsmen.cachecontrol.keys.Key;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectiveCacheFactory implements CacheFactory
{
	private final Constructor<? extends ComptrolledCache> dynamicCacheConstructor;

	public ReflectiveCacheFactory(final @NotNull Class<? extends ComptrolledCache> dynamicallyCreateCachesOfThisType)
	{
		this.dynamicCacheConstructor = findDynamicCacheConstructor(dynamicallyCreateCachesOfThisType);
	}

	@SuppressWarnings("unchecked")
	@NotNull
	public <V> ComptrolledCache<V> create(@NotNull final Key<V> identifier)
	{
		try
		{
			return (ComptrolledCache<V>) dynamicCacheConstructor.newInstance(identifier);
		}
		catch (InstantiationException e)
		{
			throw new UnsupportedOperationException("This Cashier could not create a dynamic cache", e);
		}
		catch (IllegalAccessException e)
		{
			throw new UnsupportedOperationException("This Cashier could not create a dynamic cache", e);
		}
		catch (InvocationTargetException e)
		{
			throw new UnsupportedOperationException("This Cashier could not create a dynamic cache", e);
		}
	}

	private static Constructor<? extends ComptrolledCache> findDynamicCacheConstructor(final Class<? extends ComptrolledCache> dynamicallyCreateCachesOfThisType)
	{
		try
		{
			return dynamicallyCreateCachesOfThisType.getConstructor(Key.class);
		}
		catch (NoSuchMethodException e)
		{
			throw new IllegalArgumentException("Could not obtain the unary constructor taking Key for dynamicallyCreateCachesOfThisType", e);
		}
	}
}
